package atom.core3.security.help;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.Serializable;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Enumeration;

import atom.core0.util.Base16;
import sun.misc.BASE64Decoder;
import sun.security.x509.X509CertImpl;
import es.sing.util.CertificateUtils;
import es.sing.util.GeneraClaves;
import es.sing.util.X509Subject;

public class CertInfo implements Serializable
{
	private PrivateKey priKey;
	private PublicKey pubKey;
	private X509Certificate cer;
	private String issue;

	public CertInfo()
	{
		// 修改安全通道设置
		Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
	}

	// algorithm="RSA" signAlgorithm="MD5WithRSA"
	public void CreatPKCS12(CertInfo caCertInfo, String algorithm, String signAlgorithm, int limitday, String userIssue) throws Exception
	{
		KeyPair keyPair = GeneraClaves.generaParClaves(1024, algorithm);
		priKey = keyPair.getPrivate();
		pubKey = keyPair.getPublic();
		this.issue = userIssue;

		// decodeX509Subject 就是把#1234变成char 转义字符
		userIssue = X509Subject.decodeX509Subject(issue);

		java.util.Random usercertserial = new java.util.Random();
		int nserie = usercertserial.nextInt();

		// 产生客户端证书
		cer = CertificateUtils.crearCert(pubKey, caCertInfo.getPriKey(), caCertInfo.getPubKey(), caCertInfo.getIssue(), userIssue, nserie, limitday,
				signAlgorithm);

	}

	// pfxFileName="d:/caca.pfx"
	// 读取PKCS12格式的key（私钥），和公钥
	public void ShowAllKeyFromPKCS12(String pfxFileName, String passowrd) throws Exception
	{
		KeyStore keystoreCA = KeyStore.getInstance("PKCS12", "BC");
		FileInputStream fis = null;
		try
		{
			// 读取CA根证书
			fis = new FileInputStream(pfxFileName);
			keystoreCA.load(fis, passowrd.toCharArray());

			ShowAllKeyFromKeyStore(keystoreCA, passowrd);

		}
		catch (Exception e)
		{
			if (fis != null)
				fis.close();
			throw e;
		}
		if (fis != null)
			fis.close();

	}

	public void ShowAllKeyFromJKS(String pfxFileName, String passowrd) throws Exception
	{
		KeyStore keystoreCA = KeyStore.getInstance("JKS");
		FileInputStream fis = null;
		try
		{
			// 读取CA根证书
			fis = new FileInputStream(pfxFileName);
			keystoreCA.load(fis, passowrd.toCharArray());

			ShowAllKeyFromKeyStore(keystoreCA, passowrd);

		}
		catch (Exception e)
		{
			if (fis != null)
				fis.close();
			throw e;
		}
		if (fis != null)
			fis.close();

	}

	public void ShowAllKeyFromKeyStore(KeyStore keystoreCA, String passowrd) throws Exception
	{
		Enumeration aliases = keystoreCA.aliases();
		String keyAlias = null;
		if (aliases != null)
		{
			while (aliases.hasMoreElements())
			{
				keyAlias = (String) aliases.nextElement();
				// 获取CA私钥
				priKey = (PrivateKey) (keystoreCA.getKey(keyAlias, passowrd.toCharArray()));
				cer = (X509Certificate) (keystoreCA.getCertificate(keyAlias));
				System.out.println("keyAlias is [" + keyAlias + "]");
				if (priKey == null)
					System.out.println("priKey is null");
				else
					System.out.println("priKey is: " + priKey.getAlgorithm());
					//System.out.println("priKey is " + priKey);
				System.out.println("cer    is:"+cer.getSubjectDN().toString());
				//System.out.println(cer);
				System.out.println("=============================");
			}
		}

	}

	// 读取第一个非空的私钥 以及对应的公钥证书
	// 读取PKCS12格式的key（私钥）pfx格式
	public void ReadKeyFromPKCS12(String pfxFileName, String passowrd) throws Exception
	{
		KeyStore keystoreCA = KeyStore.getInstance("PKCS12", "BC");
		FileInputStream fis = null;
		try
		{
			fis = new FileInputStream(pfxFileName);
			// 读取CA根证书
			keystoreCA.load(fis, passowrd.toCharArray());

			Enumeration aliases = keystoreCA.aliases();
			String keyAlias = null;
			if (aliases != null)
			{
				while (aliases.hasMoreElements())
				{
					keyAlias = (String) aliases.nextElement();
					// 获取CA私钥
					priKey = (PrivateKey) (keystoreCA.getKey(keyAlias, passowrd.toCharArray()));
					// 获取CA证书
					cer = (X509Certificate) (keystoreCA.getCertificate(keyAlias));
					if (priKey != null)
						break;
				}
			}

			// 获取CA公钥
			pubKey = cer.getPublicKey();
			// 获取CA公钥
			issue = cer.getSubjectDN().toString();
			issue = X509Subject.decodeX509Subject(issue);
		}
		catch (Exception e)
		{
			if (fis != null)
				fis.close();
			throw e;
		}
		if (fis != null)
			fis.close();

	}

	// pfx 二进制
	// alias公私钥用同一个可以取到
	// 读取PKCS12格式的key（私钥），和公钥 根据指定的名字
	public void ReadKeyFromPKCS12(String pfxFileName, String passowrd, String alias) throws Exception
	{
		KeyStore keystoreCA = KeyStore.getInstance("PKCS12", "BC");
		// 读取CA根证书
		keystoreCA.load(new FileInputStream(pfxFileName), passowrd.toCharArray());
		// 获取CA私钥
		priKey = (PrivateKey) (keystoreCA.getKey(alias, null));
		// 获取CA证书
		cer = (X509Certificate) (keystoreCA.getCertificate(alias));
		// 获取CA公钥
		pubKey = cer.getPublicKey();
		// 获取CA公钥
		issue = cer.getSubjectDN().toString();
		issue = X509Subject.decodeX509Subject(issue);

	}
	public void ReadKeyFromJKS(String pfxFileName, String passowrd,String alias) throws Exception
	{
		KeyStore keystoreCA = KeyStore.getInstance("JKS");
		FileInputStream fis = null;
		try
		{
			// 读取CA根证书
			fis = new FileInputStream(pfxFileName);
			keystoreCA.load(fis, passowrd.toCharArray());

			priKey = (PrivateKey) (keystoreCA.getKey(alias, passowrd.toCharArray()));
			cer = (X509Certificate) (keystoreCA.getCertificate(alias));
			// 获取公钥
			pubKey = cer.getPublicKey();
			issue = cer.getSubjectDN().toString();
			issue = X509Subject.decodeX509Subject(issue);
			

		}
		catch (Exception e)
		{
			if (fis != null)
				fis.close();
			throw e;
		}
		if (fis != null)
			fis.close();
		
	}
	// 从X509证书文件读取公钥,Certificate只含有公钥
	// .crt .cer文件都可以读取 .cer是IE导出的公钥证书（der格式）
	// -----BEGIN CERTIFICATE-----开始 文件头不许有其它内容
	// -----END CERTIFICATE-----

	// cer公钥证书 二进制
	public void ReadPublicKeyFromX509Certificate(String certFileName) throws Exception
	{
		FileInputStream in1 = new FileInputStream(certFileName);
		ReadPublicKeyFromX509Certificate(in1);
		in1.close();
	}

	public void ReadPublicKeyFromX509Certificate(InputStream in1) throws Exception
	{
		CertificateFactory cf = CertificateFactory.getInstance("X.509");
		java.security.cert.Certificate cac = cf.generateCertificate(in1);
		in1.close();
		cer = (X509Certificate) cac;
		pubKey = cac.getPublicKey();

	}

	// pfx格式 密钥库 二进制
	public static void SavePrivateKeyCert_PKCS12(Certificate[] cchain, PrivateKey userPrikey, String certFileName, String privatepass, String alias)
			throws Exception
	{
		KeyStore ks = KeyStore.getInstance("PKCS12", "BC");
		ks.load(null, null);
		ks.setKeyEntry(alias, userPrikey, null, cchain);
		SavePrivateKey(ks,certFileName,privatepass);
	}

	// jks格式 二进制
	public static void SavePrivateKeyCert_JKS(Certificate[] cchain, PrivateKey userPrikey, String certFileName, String privatepass, String alias)
			throws Exception
	{
		// 保存服务器端签名证书至密钥库
		KeyStore ks = KeyStore.getInstance("JKS");
		ks.load(null, null);
		ks.setKeyEntry(alias, userPrikey, privatepass.toCharArray(), cchain);
		
		SavePrivateKey(ks,certFileName,privatepass);

	}

	// jks格式 二进制
	public static void SavePrivateKey(KeyStore ks,String certFileName, String privatepass)
			throws Exception
	{
		// 保存服务器端签名证书至密钥库
		FileOutputStream out4 = new FileOutputStream(certFileName);
		ks.store(out4, privatepass.toCharArray());
		out4.close();

	}
	// 公钥证书cer 二进制
	public static void SavePublicKeyCert(Certificate caCer, String certFileName) throws Exception
	{
		FileOutputStream caCerOut = new FileOutputStream(certFileName);// "d:/cacaCer.cer"
		caCerOut.write(caCer.getEncoded());
		caCerOut.close();

	}
	public static void SavePublicKeyCert(X509CertImpl x509Cert, String certFileName) throws Exception
	{
		FileOutputStream caCerOut = new FileOutputStream(certFileName);// "d:/cacaCer.cer"
		caCerOut.write(x509Cert.getEncoded());
		caCerOut.close();

	}
	
	public PrivateKey getPriKey()
	{
		return priKey;
	}

	public PublicKey getPubKey()
	{
		return pubKey;
	}

	public String getIssue()
	{
		return issue;
	}

	public X509Certificate getCer()
	{
		return cer;
	}

	// 读取PKCS8格式的私钥(openssl 生成的就是该格式)
	// -----BEGIN CERTIFICATE-----开始 文件头允许有其它内容
	// -----END CERTIFICATE-----
	public void ReadPrivateKeyFromPKCS8(String keyfile, String password) throws Exception
	{
		String str = ReadCerFile(keyfile);

		// 编码转换，进行BASE64解码
		BASE64Decoder base64decoder = new BASE64Decoder();
		byte[] b = base64decoder.decodeBuffer(str);
		// 生成私匙
		ReadPrivateKeyFromRaw(b);
	}

	// 读取原始私钥
	public void ReadPrivateKeyFromRaw(String keyfile) throws Exception
	{

		FileInputStream br = new FileInputStream(keyfile);

		byte[] b1 = new byte[2000];
		int k = br.read(b1);

		byte[] b = new byte[k];
		System.arraycopy(b1, 0, b, 0, k);
		// 生成私匙
		ReadPrivateKeyFromRaw(b);

	}

	// 读取原始私钥
	public void ReadPrivateKeyFromRaw(byte[] rawprivatekey) throws Exception
	{
		// 生成私匙
		// KeyFactory kf = KeyFactory.getInstance("RSA");//"SunJSSE"
		KeyFactory kf = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rawprivatekey);
		priKey = kf.generatePrivate(keySpec);
	}

	// 读取X509格式公钥 :base64编码的raw格式
	// 读取X509格式公钥pem证书
	// -----BEGIN CERTIFICATE-----
	// -----END CERTIFICATE-----
	// 前面任意字符
	public void ReadPublicKeyFromX509(String certfile) throws Exception
	{
		String str = ReadCerFile(certfile);
		// 编码转换，进行BASE64解码
		BASE64Decoder base64decoder = new BASE64Decoder();
		byte[] b = base64decoder.decodeBuffer(str);

		// 生成公钥
		ReadPublicKeyFromRaw(b);

	}

	// 读取原始公钥
	public void ReadPublicKeyFromRaw(String keyfile) throws Exception
	{

		FileInputStream br = new FileInputStream(keyfile);

		byte[] b1 = new byte[2000];
		int k = br.read(b1);

		byte[] b = new byte[k];
		System.arraycopy(b1, 0, b, 0, k);
		// 生成公钥
		ReadPublicKeyFromRaw(b);

	}

	// 读取原始公钥
	public void ReadPublicKeyFromRaw(byte[] rawpublickey) throws Exception
	{

		// 生成公钥
		// KeyFactory kf = KeyFactory.getInstance("RSA");//"SunJSSE"
		KeyFactory kf = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(rawpublickey);
		pubKey = kf.generatePublic(keySpec);
	}

	// 根据128位大整数生成公钥
	public void ReadRawPublicKeyFromBigInt(String base16pubkey) throws Exception
	{
		byte e[] =
		{ 0, 1, 0, 1 };

		byte[] bigint = Base16.hexStrToBytes("00" + base16pubkey);
		try
		{
			KeyFactory keyf = KeyFactory.getInstance("RSA");
			RSAPublicKeySpec pubkf = new RSAPublicKeySpec(new BigInteger(bigint), new BigInteger(e));
			pubKey = keyf.generatePublic(pubkf);
		}
		catch (Exception ex)
		{
			System.out.println(ex.getMessage());
		}
	}

	public String ReadCerFile(String certfile) throws Exception
	{
		FileReader fr = new FileReader(certfile);
		String str = "";
		try
		{
			BufferedReader br = new BufferedReader(fr);
			String s = "";
			boolean bFlag = false;
			while (true)
			{
				s = br.readLine();
				if (s == null)
					break;
				s.trim();
				if (s.equals(""))
					continue;

				if (s.charAt(0) == '-')
				{
					if (bFlag)
						break;
					bFlag = true;
					continue;
				}
				// 提取证书
				if (bFlag)
				{
					str += s + "\r";
					continue;
				}

			}
		}
		catch (Exception e)
		{
			if (fr != null)
				fr.close();
		}
		if (fr != null)
			fr.close();

		if (str.equals(""))
		{
			throw new Exception("读取证书错误");
		}
		return str;
		// 编码转换，进行BASE64解码
		// BASE64Decoder base64decoder = new BASE64Decoder();
		// byte[] b = base64decoder.decodeBuffer(str);

	}

	public String ReadSimpleCerFile(String certfile) throws Exception
	{
		FileReader fr = new FileReader(certfile);
		String str = "";
		try
		{

			BufferedReader br = new BufferedReader(fr);
			String s = br.readLine();

			s = br.readLine();
			while (s.charAt(0) != '-')
			{
				str += s + "\r";
				s = br.readLine();
			}
		}
		catch (Exception e)
		{
			if (fr != null)
				fr.close();
		}
		if (fr != null)
			fr.close();

		if (str.equals(""))
		{
			throw new Exception("读取证书错误");
		}
		return str;
	}
}
